#ifndef GPU_PROGRAM_H_
#define GPU_PROGRAM_H_


#include <map>
#include <string>
#include <vector>

#include "arithmetic.h"
#include "render_system/gl_render_system_define.h"

class GPUProgram
{
public:
    enum ShaderType {Vertex, Geometry, Fragment};

public:
    GL_RENDER_SYSTEM_API GPUProgram(void);
    GL_RENDER_SYSTEM_API ~GPUProgram(void);

public:
    GL_RENDER_SYSTEM_API void addShaderFile(const ShaderType type, const std::string& shader_source);
    GL_RENDER_SYSTEM_API void use();
    GL_RENDER_SYSTEM_API void unuse();

    GL_RENDER_SYSTEM_API void setUniform(const std::string& name, const int val);
    GL_RENDER_SYSTEM_API void setUniform(const std::string& name, const float val);
    GL_RENDER_SYSTEM_API void setUniform(const std::string& name, const glm::vec2& vec);
    GL_RENDER_SYSTEM_API void setUniform(const std::string& name, const glm::vec3& vec);
    GL_RENDER_SYSTEM_API void setUniform(const std::string& name, const glm::vec4& vec);
    GL_RENDER_SYSTEM_API void setUniform(const std::string& name, const glm::mat4& mat);

    GL_RENDER_SYSTEM_API int getActiveAttribute(const std::string& name) const;
    GL_RENDER_SYSTEM_API int getActiveUniform(const std::string& name) const;

    GL_RENDER_SYSTEM_API void printActiveAttributes();
    GL_RENDER_SYSTEM_API void printActiveUniforms();

private:
    void _create();
    void _clean();
    void _getActiveAttributes();
    void _getActiveUniforms();

private:
    unsigned int               _programID;
    std::vector<unsigned int>  _shaders;
    std::map<std::string, int> _activeAttributesMap;
    std::map<std::string, int> _activeUniformsMap;
};

#endif
